package com.xijia.example.manage.all.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.xijia.example.enums.SiteToolDic;
import com.xijia.example.manage.all.model.dto.SiteCheckLogDTO;
import com.xijia.example.manage.all.model.entity.SiteCheckLog;
import com.xijia.example.manage.all.service.SiteCheckLogService;
import com.xijia.example.util.SiteCheckUtil;
import com.xijia.example.util.res.SiteCertCheckResult;
import com.xijia.example.util.res.SiteCheckResult;
import io.github.wslxm.springbootplus2.core.utils.date.XjLocalDateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import io.github.wslxm.springbootplus2.core.base.model.BasePage;
import io.github.wslxm.springbootplus2.core.constant.SymbolConst;
import io.github.wslxm.springbootplus2.core.base.service.impl.BaseServiceImpl;
import io.github.wslxm.springbootplus2.core.utils.XjBeanUtil;
import com.xijia.example.manage.all.mapper.SiteMapper;
import com.xijia.example.manage.all.service.SiteService;
import com.xijia.example.manage.all.model.entity.Site;
import com.xijia.example.manage.all.model.vo.SiteVO;
import com.xijia.example.manage.all.model.dto.SiteDTO;
import com.xijia.example.manage.all.model.query.SiteQuery;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.net.SocketTimeoutException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 站点管理 ServiceImpl
 *
 * <p>
 * ::本代码由[兮家小二]提供的代码生成器生成,如有问题,请手动修改 ::作者CSDN:https://blog.csdn.net/qq_41463655
 * </p>
 * @author ws
 * @email 1720696548@qq.com
 * @date 2024-09-25 11:36:42
 */
@Service
public class SiteServiceImpl extends BaseServiceImpl<SiteMapper, Site> implements SiteService {

    @Autowired
    private SiteCheckLogService siteCheckLogService;

    @Override
    public BasePage<SiteVO> findPage(SiteQuery query) {
        LambdaQueryWrapper<Site> queryWrapper = new LambdaQueryWrapper<Site>();
        queryWrapper.likeRight(StringUtils.isNotBlank(query.getName()), Site::getName, query.getName());
        queryWrapper.likeRight(StringUtils.isNotBlank(query.getSite()), Site::getSite, query.getSite());
        queryWrapper.likeRight(StringUtils.isNotBlank(query.getType()), Site::getType, query.getType());
        queryWrapper.likeRight(StringUtils.isNotBlank(query.getVisitState()), Site::getVisitState, query.getVisitState());
        queryWrapper.likeRight(StringUtils.isNotBlank(query.getIfHttps()), Site::getIfHttps, query.getIfHttps());
        queryWrapper.last(" order by " + query.getSort() + " " + query.getOrder());
        Page<Site> page = this.page(new Page<>(query.getCurrent(), query.getSize()), queryWrapper);
        BasePage<SiteVO> pageVo = XjBeanUtil.pageVo(page, SiteVO.class);
        for (SiteVO record : pageVo.getRecords()) {
            if (record.getHttpsExpirationTime() == null) {
                continue;
            }
            long dayNum = XjLocalDateTimeUtil.betweenTwoTime(LocalDateTime.now(), record.getHttpsExpirationTime(), ChronoUnit.DAYS);
            record.setHttpsDayNum(dayNum);
        }
        return pageVo;
    }

    @Override
    public SiteVO findId(String id) {
        return XjBeanUtil.convert(this.getById(id), SiteVO.class);
    }

    @Override
    public String insert(SiteDTO dto) {
        Site entity = dto.convert(Site.class);
        boolean b = this.save(entity);
        return entity.getId();
    }

    @Override
    public boolean upd(String id, SiteDTO dto) {
        Site entity = dto.convert(Site.class);
        entity.setId(id);
        return this.updateById(entity);
    }

    @Override
    public boolean del(String id) {
        return this.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean siteChecks(String id) {
        Site site = this.getById(id);
        // 标记为正常的状态
        List<String> normalCodes = new ArrayList<>();
        if (StringUtils.isNotBlank(site.getNormalCodes())) {
            normalCodes.addAll(Arrays.asList(site.getNormalCodes().split(",")));
        }
        // 访问检查
        SiteCheckLogDTO siteCheckLog = new SiteCheckLogDTO();
        siteCheckLog.setSiteId(site.getId());
        siteCheckLog.setSite(site.getSite());
        siteCheckLog.setType(SiteToolDic.SiteCheckType.VISIT.getValue());
        SiteCheckResult visitResult = SiteCheckUtil.siteVisitCheck(site.getSite(), normalCodes);
        siteCheckLog.setState(visitResult.getState() ? SiteToolDic.VisitState.NORMAL.getValue() : SiteToolDic.VisitState.ERROR.getValue());
        siteCheckLog.setResult(visitResult.getResult());
        siteCheckLogService.insert(siteCheckLog);

        // 访问正常并且配置了 https
        SiteCertCheckResult certResult = null;
        normalCodes.add("200");
        if (site.getIfHttps().equals("yes") && normalCodes.contains(visitResult.getStatus() + "")) {
            // https 检查
            siteCheckLog = new SiteCheckLogDTO();
            siteCheckLog.setSiteId(site.getId());
            siteCheckLog.setSite(site.getSite());
            siteCheckLog.setType(SiteToolDic.SiteCheckType.HTTPS.getValue());
            // 检查后的状态
            certResult = SiteCheckUtil.checkCertificateExpiry(site.getSite());
            siteCheckLog.setState(certResult.getState() ? SiteToolDic.VisitState.NORMAL.getValue() : SiteToolDic.VisitState.ERROR.getValue());
            siteCheckLog.setResult(certResult.getResult());
            siteCheckLogService.insert(siteCheckLog);
        }
        // 更新数据
        String ip = visitResult.getIp();
        if (certResult == null) {
            // 没有配置 https 的检查
            site.setIp(ip);
            site.setHttpsExpirationTime(null);
            site.setLastCheckLog(visitResult.getResult());
            site.setVisitState(visitResult.getState() ? SiteToolDic.VisitState.NORMAL.getValue() : SiteToolDic.VisitState.ERROR.getValue());
            this.updateById(site);
            return visitResult.getState();
        } else {
            // 配置了 https 的检查
            site.setIp(ip);
            site.setHttpsExpirationTime(certResult.getEndTime());
            site.setLastCheckLog(visitResult.getResult() + " | " + certResult.getResult());
            site.setVisitState(visitResult.getState() && certResult.getState() ? SiteToolDic.VisitState.NORMAL.getValue() : SiteToolDic.VisitState.ERROR.getValue());
            this.updateById(site);
            return visitResult.getState() && certResult.getState();
        }
    }

    @Override
    public boolean siteChecksAll() {
        List<Site> list = this.list(new LambdaQueryWrapper<Site>().select(Site::getId));
        for (Site site : list) {
            this.siteChecks(site.getId());
        }
        return true;
    }
}
